HerokuでCluster modeのnode.jsプロセスを起動するとそれぞれがメモリを手加減なしに使おうとするので--max-old-space-sizeの指定が必須
実装したので経過観察
環境変数CLUSTER_WORKER_NODE_OPTIONSに--max-old-space-size=512を設定した後の経過観察
Node.js 22あたりのメモリ使用量の挙動はこんな感じ、のはずshokai.icon
サーバー環境にある最大メモリ量を認知しており、ギリギリまで使おうとする
Node.jsはHeroku dynoに搭載されているメモリ量を誤認している
基本的には、1プロセスあたり1.5GB弱までしかメモリ確保しない
V8の仕様
つまりメモリ2GB積んでるサーバーに、2プロセスforkでnode:clusterを起動すると
2プロセスが1.5GBまで使おうとする
これがCosenseのweb dynoのメモリ使用量が爆発してるけどなぜかなんともないで起きている事象だと思うshokai.icon
Standard-2X dynoはメモリ1GBだが、VMには2GBまで解放されている
ちょっとオーバーしてもいいよ
オーバーし続けたらkillするけど
という事のはずだが、今なぜかR14 - Memory Quota Exceededはアラートされてもプロセスのkillは行われなくて、謎な感じになっている
cluster.forkで作る子プロセスに--max-old-space-sizeを設定する環境変数を用意する
これがCosenseの運用ではちょうど良いだろうshokai.icon
全てのプロセスに一貫して--max-old-space-size指定してしまうと、batch処理とかにも影響を与えてしまう
環境変数CLUSTER_WORKER_NODE_OPTIONS
cluster modeのworkerに渡すNODE_OPTIONS
--max-old-space-sizeなど、nodeの環境変数オプションを何でも渡せる
下手にcluster数で割り算するとか、気の利かせた事はしない
シンプルにNODE_OPTIONSを露出させる
下手に気を利かせた抽象化をせず、内部構造を露出させる方が理解も運用もしやすいはずだ
max-old-space-sizeを%で指定できるようになったなどの改善や仕様変更にも、各自の判断で対応しやすい
WEB_MEMORYは使わない
WEB_MEMORYがある場合、自動的に子プロセスの--max-old-space-sizeに反映させてもよい、ような気もするが
その方式では、メモリ量しか設定できない
--max-old-space-size以外の値も設定したくなった場合に邪魔になりそう
「環境変数WEB_MEMORYがあったら--max-old-space-sizeが自動的にセットされる」という仕様は、たぶん真面目にnode.jsアプリの運用やチューニングをやる時に邪魔になるshokai.icon
done.icon https://github.com/nota/scrapbox/pull/7911
https://gyazo.com/01a3e7f4eb8b3be5d91d8481636fb859
cluster modeでは、親プロセスの環境変数は子プロセスに引き継がれる仕様があるが
https://gyazo.com/deb46f9dc938d70dde77a91d11202fec
CLUSTER_WORKER_NODE_OPTIONSを使うと、引き継がれる環境変数NODE_OPTIONSを上書きできる
https://gyazo.com/72833935a54be1cfd22030e331de42d7
親と子それぞれにNODE_OPTIONSを設定できるという事
NODE_OPTIONSもCLUSTER_WORKER_NODE_OPTIONSもどちらも設定していない場合
https://gyazo.com/9f940b92a5419651ce73778aa2dea37f
masterにもworkerにも何も設定されない事がわかる